Warning, /plasma/plasma-bigscreen/components/qml/TileRepeater.qml is written in an unsupported language. File is not indexed.

0001  /*
0002  * SPDX-FileCopyrightText: 2022 Aditya Mehra <aix.m@outlook.com>
0003  * SPDX-FileCopyrightText: 2020 Marco Martin <mart@kde.org>
0004  *
0005  * SPDX-License-Identifier: GPL-2.0-or-later
0006  */
0007 
0008 import QtQuick 2.14
0009 import QtQuick.Layouts 1.14
0010 import QtQuick.Window 2.14
0011 import QtQuick.Controls 2.14 as Controls
0012 import org.kde.plasma.core 2.0 as PlasmaCore
0013 import org.kde.kirigami 2.12 as Kirigami
0014 import org.kde.mycroft.bigscreen 1.0 as BigScreen
0015 
0016 FocusScope {
0017     id: root
0018     signal activated
0019     property string title
0020     property alias view: view
0021     property alias delegate: view.delegate
0022     property alias model: view.model
0023     property alias currentIndex: view.currentIndex
0024     property alias currentItem: view.currentItem
0025     property alias count: view.count
0026     Layout.fillWidth: true
0027 
0028     implicitHeight: view.implicitHeight + header.implicitHeight
0029 
0030     property real columns: {
0031         var v = root.compactMode ? 7.5 : 5.5
0032         if (view.Window.window.width <= 1280 && view.Window.window.width > 1024) {
0033             v = root.compactMode ? 6.5 : 4.5
0034         } else if (view.Window.window.width <= 1024 && view.Window.window.width > 800) {
0035             v = root.compactMode ? 5.5 : 3.5
0036         } else if (view.Window.window.width <= 800) {
0037             v = root.compactMode ? 4.5 : 2.5
0038         }
0039         return v
0040     }
0041 
0042     property alias cellWidth: view.cellWidth
0043     property alias cellHeight: view.cellHeight
0044     readonly property real screenRatio: view.Window.window ? view.Window.window.width / view.Window.window.height : 1.6
0045 
0046     property bool compactMode: false
0047     property Item navigationUp
0048     property Item navigationDown
0049 
0050     onActiveFocusChanged: {
0051         if (!activeFocus) {
0052             return;
0053         }
0054 
0055         // Update currentItem if needed
0056         view.currentIndexChanged();
0057 
0058         if (!currentItem) {
0059             return;
0060         }
0061 
0062         currentItem.forceActiveFocus();
0063     }
0064 
0065     Kirigami.Heading {
0066         id: header
0067         anchors {
0068             left: parent.left
0069             right: parent.right
0070             top: parent.top
0071         }
0072         text: title
0073         layer.enabled: true
0074         color: "white"
0075     }
0076 
0077     Flickable {
0078         id: view
0079         anchors {
0080             left: parent.left
0081             right: parent.right
0082             top: header.baseline
0083             bottom: parent.bottom
0084             topMargin: Kirigami.Units.largeSpacing*2
0085             leftMargin: -Kirigami.Units.largeSpacing
0086         }
0087         readonly property int cellWidth: root.width / columns + (PlasmaCore.Units.gridUnit / 2)
0088         property int cellHeight: root.compactMode ? cellWidth + units.gridUnit * 3 : cellWidth * 0.75
0089         property int currentIndex: 0
0090         property alias count: repeater.count
0091         property alias model: repeater.model
0092         property alias delegate: repeater.delegate
0093         readonly property Item currentItem: layout.children[currentIndex]
0094 
0095         function indexAt(x,y) {
0096             return Math.max(0, Math.min(count - 1, Math.round(x/cellWidth)));
0097         }
0098 
0099         focus: true
0100 
0101         implicitHeight: cellHeight
0102         contentWidth: layout.width
0103         contentHeight: height
0104         onCurrentItemChanged: {
0105             if (!currentItem) {
0106                 return;
0107             }
0108 
0109             currentItem.forceActiveFocus();
0110             slideAnim.slideToIndex(currentIndex);
0111         }
0112 
0113         onMovementEnded: currentIndex = Math.min(count-1, Math.round((contentX + cellWidth) / cellWidth))
0114         onFlickEnded: movementEnded()
0115 
0116         NumberAnimation {
0117             id: slideAnim
0118             target: view
0119             property: "contentX"
0120             duration: 250
0121 
0122             function slideToIndex(index) {
0123                 slideAnim.running = false;
0124                 slideAnim.from = view.contentX;
0125                 slideAnim.to = Math.max(0, view.cellWidth * view.currentIndex);
0126                 slideAnim.restart();
0127             }
0128         }
0129 
0130         Row {
0131             id: layout
0132             anchors {
0133                 top: parent.top
0134                 bottom: parent.bottom
0135             }
0136             spacing: 0
0137 
0138             Repeater {
0139                 id: repeater
0140                 // Update currentItem if needed
0141                 onChildrenChanged: view.currentIndexChanged();
0142             }
0143 
0144             // Spacer
0145             Item {
0146                 width: view.width - view.cellWidth*2
0147                 height: 1
0148             }
0149         }
0150 
0151         Keys.onLeftPressed: {
0152             if (currentIndex > 0) {
0153                 BigScreen.NavigationSoundEffects.playMovingSound();
0154                 currentIndex = Math.max(0, currentIndex - 1);
0155             }
0156         }
0157         Keys.onRightPressed: {
0158             if (currentIndex < count - 1) {
0159                 BigScreen.NavigationSoundEffects.playMovingSound();
0160                 currentIndex = Math.min(count - 1, currentIndex + 1);
0161             }
0162         }
0163 
0164         Keys.onDownPressed:  {
0165             if (!root.navigationDown) {
0166                 return;
0167             }
0168 
0169             BigScreen.NavigationSoundEffects.playMovingSound();
0170 
0171             if (root.navigationDown instanceof TileView ||
0172                 root.navigationDown instanceof TileRepeater) {
0173                 root.navigationDown.currentIndex = Math.min(Math.floor(root.navigationDown.view.indexAt(root.navigationDown.view.contentX, height/2)), root.navigationDown.view.count - 1);
0174 
0175                 if (root.navigationDown.currentIndex < 0) {
0176                     root.navigationDown.currentIndex = view.currentIndex > 0 ? root.navigationDown.view.count - 1 : 0
0177                 }
0178             }
0179 
0180             root.navigationDown.forceActiveFocus();
0181         }
0182 
0183         Keys.onUpPressed:  {
0184             if (!root.navigationUp) {
0185                 return;
0186             }
0187 
0188             BigScreen.NavigationSoundEffects.playMovingSound();
0189 
0190             if (root.navigationUp instanceof TileView ||
0191                 root.navigationUp instanceof TileRepeater) {
0192                 root.navigationUp.currentIndex = Math.min(Math.floor(root.navigationUp.view.indexAt(root.navigationUp.view.contentX, height/2)), root.navigationUp.view.count - 1);
0193 
0194                 if (root.navigationUp.currentIndex < 0) {
0195                     root.navigationUp.currentIndex = view.currentIndex > 0 ? root.navigationUp.view.count - 1 : 0
0196                 }
0197             }
0198 
0199             root.navigationUp.forceActiveFocus();
0200         }
0201     }
0202 }