9 import QtQuick.Controls 2.15 as QQC2
10 import QtGraphicalEffects 1.0 as GE
11 import org.kde.kirigami 2.19 as Kirigami
12 import org.kde.kirigami.templates 2.2 as KT
83 property bool refreshing:
false
90 property bool supportsRefreshing:
false
96 property Flickable flickable: Flickable {}
97 onFlickableChanged: scrollView.contentItem = flickable;
103 property int verticalScrollBarPolicy
109 property int horizontalScrollBarPolicy: QQC2.ScrollBar.AlwaysOff
111 default property alias scrollablePageData: itemsParent.data
112 property alias scrollablePageChildren: itemsParent.children
117 property QtObject mainItem
119 print(
"Warning: the mainItem property is deprecated");
120 scrollablePageData.push(mainItem);
132 property bool keyboardNavigationEnabled:
true
135 contentHeight: flickable ? flickable.contentHeight : 0
137 let height = contentHeight + topPadding + bottomPadding;
138 if (header && header.visible) {
139 height += header.implicitHeight;
141 if (footer && footer.visible) {
142 height += footer.implicitHeight;
149 if (flickable.contentItem) {
150 return flickable.contentItem.implicitWidth;
152 return contentItem.implicitWidth + leftPadding + rightPadding;
159 Kirigami.Theme.inherit:
false
160 Kirigami.Theme.colorSet: flickable && flickable.hasOwnProperty(
"model") ? Kirigami.Theme.View : Kirigami.Theme.Window
163 if (root.keyboardNavigationEnabled && root.flickable) {
164 if ((
"currentItem" in root.flickable) && root.flickable.currentItem) {
165 return [ root.flickable.currentItem, root.flickable ];
167 return [ root.flickable ];
174 contentItem: QQC2.ScrollView {
177 top: (root.header && root.header.visible)
180 : (globalToolBarItem && globalToolBarItem.parent && globalToolBarItem.visible
181 ? globalToolBarItem.parent.bottom
183 bottom: (root.footer && root.footer.visible) ? root.footer.top : parent.bottom
186 topMargin: root.refreshing ? busyIndicatorLoader.height : 0
187 Behavior on topMargin {
189 easing.type: Easing.InOutQuad
190 duration: Kirigami.Units.longDuration
194 QQC2.ScrollBar.horizontal.policy: root.horizontalScrollBarPolicy
195 QQC2.ScrollBar.vertical.policy: root.verticalScrollBarPolicy
202 width: root.flickable.width
203 height: Math.max(root.flickable.height, implicitHeight)
206 for (
const i in itemsParent.visibleChildren) {
207 const child = itemsParent.visibleChildren[i];
208 if (child.implicitHeight <= 0) {
209 impl = Math.max(impl, child.height);
211 impl = Math.max(impl, child.implicitHeight);
214 return impl + itemsParent.anchors.topMargin + itemsParent.anchors.bottomMargin;
218 property Flickable flickable
221 leftMargin: root.leftPadding
222 topMargin: root.topPadding
223 rightMargin: root.rightPadding
224 bottomMargin: root.bottomPadding
227 const child = children[children.length - 1];
228 if (child instanceof QQC2.ScrollView) {
229 print(
"Warning: it's not supported to have ScrollViews inside a ScrollablePage")
234 target: root.flickable
235 property:
"bottomMargin"
236 value: root.bottomPadding
237 restoreMode: Binding.RestoreBinding
242 id: busyIndicatorLoader
244 y: root.flickable.verticalLayoutDirection === ListView.BottomToTop
245 ? -root.flickable.contentY + root.flickable.originY + height
246 : -root.flickable.contentY + root.flickable.originY - height
247 width: root.flickable.width
248 height: Kirigami.Units.gridUnit * 4
249 active: root.supportsRefreshing
251 sourceComponent: Item {
252 id: busyIndicatorFrame
257 anchors.centerIn: parent
258 running: root.refreshing
259 visible: root.refreshing
266 margins: Kirigami.Units.smallSpacing
269 visible: supportsRefreshing && !refreshing && progress > 0
272 border.color: Kirigami.Theme.backgroundColor
273 border.width: Kirigami.Units.smallSpacing
274 property real progress: supportsRefreshing && !refreshing ? (busyIndicatorLoader.y / busyIndicatorFrame.height) : 0
277 source: spinnerProgress
278 visible: spinnerProgress.visible
279 anchors.fill: spinnerProgress
281 GradientStop { position: 0.00; color: Kirigami.Theme.highlightColor }
282 GradientStop { position: spinnerProgress.progress; color: Kirigami.Theme.highlightColor }
283 GradientStop { position: spinnerProgress.progress + 0.01; color:
"transparent" }
284 GradientStop { position: 1.00; color:
"transparent" }
289 target: busyIndicatorLoader
290 function onYChanged() {
291 if (!supportsRefreshing) {
295 if (!root.refreshing && busyIndicatorLoader.y > busyIndicatorFrame.height / 2 + topPadding) {
296 refreshTriggerTimer.running =
true;
298 refreshTriggerTimer.running =
false;
303 id: refreshTriggerTimer
306 if (!root.refreshing && busyIndicatorLoader.y > busyIndicatorFrame.height / 2 + topPadding) {
307 root.refreshing =
true;
316 let flickableFound =
false;
317 for (
const i in itemsParent.data) {
318 const child = itemsParent.data[i];
319 if (child instanceof Flickable) {
322 child.activeFocusOnTab =
true;
323 root.flickable = child;
324 flickableFound =
true;
325 if (child instanceof ListView) {
326 child.keyNavigationEnabled =
true;
327 child.keyNavigationWraps =
false;
329 }
else if (child instanceof Item) {
330 child.anchors.left = itemsParent.left;
331 child.anchors.right = itemsParent.right;
332 }
else if (child instanceof KT.OverlaySheet) {
334 if (child.parent === itemsParent || child.parent ===
null) {
340 if (flickableFound) {
341 scrollView.contentItem = root.flickable;
342 root.flickable.
parent = scrollView;
345 if (root.activeFocus) {
346 root.flickable.forceActiveFocus();
350 root.flickable.anchors.fill = undefined;
351 root.flickable.anchors.left = undefined;
352 root.flickable.anchors.right = undefined;
353 root.flickable.anchors.top = undefined;
354 root.flickable.anchors.bottom = undefined;
356 scrollView.contentItem = root.flickable;
357 scrollingArea.parent = root.flickable.contentItem;
358 root.flickable.contentHeight =
Qt.binding(() => scrollingArea.implicitHeight - root.flickable.topMargin - root.flickable.bottomMargin);
359 root.flickable.contentWidth =
Qt.binding(() => scrollingArea.implicitWidth);
361 root.flickable.flickableDirection = Flickable.VerticalFlick;